package com.database.objects;

import japa.parser.*;
import japa.parser.ast.CompilationUnit;

import java.io.*;
import java.util.*;

import javax.persistence.*;

@Entity
@Table(name = "file_oo")
public class FileOO extends File {

	private static final long serialVersionUID = -4718426520404520071L;

	@Transient
	private CompilationUnit compilation;

	@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "file")
	private List<Class> classes = new ArrayList<Class>();

	public FileOO() {

	}

	public FileOO(String path, boolean file, Status status, Commit commit) {
		this.path = path;
		this.file = file;
		this.status = status;
		this.commit = commit;
	}

	public CompilationUnit getCompilation() {
		return compilation;
	}

	public CompilationUnit buildCompilation() throws ParseException {
		InputStream bais = new ByteArrayInputStream(baos.toByteArray());
		compilation = JavaParser.parse(bais);
		return compilation;
	}

	@Override
	public List<Class> getChilds() {
		return classes;
	}

	@Override
	public void addChild(Class clazz) {
		Class oldClass = getChildByLabel(clazz.getLabel());
		if (oldClass == null) {
			classes.add(clazz);
		}
	}

	public void markAddClasses(FileOO previousFile) {
		List<Class> validPreviousClasses = previousFile.getValidClasses();
		Iterator<Class> iterator = classes.iterator();
		while (iterator.hasNext()) {
			Class clazz = iterator.next();
			if (!validPreviousClasses.contains(clazz)) {
				clazz.markAsAdd();
			}
		}
	}

	private List<Class> getValidClasses() {
		List<Class> validClasses = new ArrayList<Class>();
		for (Class clazz : classes) {
			if (clazz.isValid()) {
				validClasses.add(clazz);
			}
		}
		return validClasses;
	}

	public void markDeletedClasses(FileOO previousFile) {
		List<Class> validPreviousClasses = previousFile.getValidClasses();
		for (Class clazz : validPreviousClasses) {
			if (!classes.contains(clazz)) {
				classes.add(new Class(clazz.getName(), Status.DELETE, this));
			}
		}
	}

	public void cloneClasses(FileOO other, Status status) {
		List<Class> validClasses = other.getValidClasses();
		for (Class clazz : validClasses) {
			if (getChildByLabel(clazz.getName()) == null) {
				classes.add(new Class(clazz.getName(), status, this));
			}
		}
	}

	@Override
	public Type getType() {
		return Type.FILE_OO;
	}

	@Override
	public boolean isFileOO() {
		return true;
	}

}